package com.jm.framework.common.utils;

import cn.hutool.core.util.StrUtil;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Objects;

/**
 * tide
 * <p>
 * BigDecimal 工具类
 * <p>
 * author: jiangjianmin
 * <p>
 * create: 2024-08-21 14:11
 **/
public class BigDecimalUtil {

    public final static BigDecimal ONE_HUNDRED = new BigDecimal("100.00");

    public static String bigDecimal2String(BigDecimal decimal) {
        return decimal == null ? StringUtils.EMPTY : decimal.toPlainString();
    }

    public static String bigDecimal2StringTrimZero(BigDecimal decimal) {
        return decimal == null ? StringUtils.EMPTY : decimal.stripTrailingZeros().toPlainString();
    }

    /*直接舍去*/
    public static String bigDecimal2String(BigDecimal decimal, int scale) {
        return decimal == null ? StringUtils.EMPTY : decimal.setScale(scale, BigDecimal.ROUND_DOWN).toPlainString();
    }

    /*四舍五入*/
    public static String bigDecimal2StringUp(BigDecimal decimal, int scale) {
        return decimal == null ? StringUtils.EMPTY : decimal.setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
    }

    /**
     * 金额前端展示格式化
     */
    // TODO: 2021/8/4 建议前端金额展示都通过该方法来格式化，保证可以统一处理
    public static String amountFrontShow(BigDecimal amount) {
        BigDecimal decimal = amountFront(amount);
        return decimal != null ? decimal.toPlainString() : null;
    }

    /**
     * 金额前端展示格式化
     */
    public static BigDecimal amountFront(BigDecimal amount) {
        // 前端金额展示格式化（当前保留2位小数，多余精度舍去）
        return amount != null ? amount.setScale(2, BigDecimal.ROUND_HALF_UP) : null;
    }

    public static String bigDecimalNull2String(BigDecimal decimal) {
        return decimal == null ? null : decimal.stripTrailingZeros().toPlainString();
    }

    public static BigDecimal formatBigDecimal(BigDecimal decimal) {
        return decimal == null ? BigDecimal.ZERO : decimal;
    }

    /**
     * 当参数不为null的时候，设置精度，直接舍去
     *
     * @param decimal
     * @param scale
     * @return
     */
    public static BigDecimal formatBigDecimalWhenNotnull(BigDecimal decimal, int scale) {
        return decimal != null ? decimal.setScale(scale, BigDecimal.ROUND_DOWN) : null;
    }

    /**
     * 当参数不为null的时候，设置精度，四舍五入
     *
     * @param decimal
     * @param scale
     * @return
     */
    public static BigDecimal formatBigDecimalWhenNotnullUp(BigDecimal decimal, int scale) {
        return decimal != null ? decimal.setScale(scale, BigDecimal.ROUND_HALF_UP) : null;
    }

    public static BigDecimal checkBigDecimal(BigDecimal decimal) {
        return decimal == null ? BigDecimal.ZERO : decimal;
    }

    /**
     * 返回折扣的描述信息
     * 比如： decimal 为  0.45 ，返回 4.5折
     * 比如： decimal 为  0.15 ，返回 1.5折
     */
    public static String discountDescr(BigDecimal decimal) {
        return decimal == null || BigDecimal.ZERO.compareTo(decimal) == 0 ? null : decimal.multiply(new BigDecimal("10")).stripTrailingZeros().toPlainString() + "折";
    }

    public static boolean isEmpty(BigDecimal decimal) {
        return decimal == null || BigDecimal.ZERO.compareTo(decimal) == 0;
    }

    public static boolean isNullOrZero(BigDecimal decimal) {
        return decimal == null || BigDecimal.ZERO.compareTo(decimal) == 0;
    }

    public static boolean isNotNull(BigDecimal decimal) {
        return decimal != null;
    }

    /**
     * 返回折扣的描述信息
     * 比如： decimal 为  0.45 ，返回 4.5折
     * 比如： decimal 为  0.15 ，返回 1.5折
     */
    public static String discountDescr(String decimalStr) {
        if (StringUtils.isBlank(decimalStr)) {
            return null;
        }
        BigDecimal decimal = new BigDecimal(decimalStr);
        return BigDecimal.ZERO.compareTo(decimal) == 0 ? null : decimal.multiply(new BigDecimal("10")).stripTrailingZeros().toPlainString() + "折";
    }

    /**
     * 扣率值 * 100 后返回 T 类型
     */
    public static <T> T multiply100Generic(String decimal, Class<T> t) {
        if (StringUtils.isBlank(decimal)) {
            return null;
        }
        if (t.getClass().equals(String.class)) {
            return (T) new BigDecimal(decimal).multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString();
        }
        return (T) new BigDecimal(decimal).multiply(new BigDecimal("100"));
    }

    public static BigDecimal multiply(BigDecimal a, BigDecimal b) {
        if (a == null || b == null) {
            return null;
        }
        return a.multiply(b);
    }

    /**
     * 指定精度
     */
    public static String bigDecimalScale(String decimal, int scale) {
        if (StringUtils.isBlank(decimal)) return null;

        return new BigDecimal(decimal).setScale(scale, BigDecimal.ROUND_HALF_UP).toPlainString();
    }

    public static String formatPercentData2String(BigDecimal decimal, int scale) {
        if (decimal == null) {
            return null;
        }
        return BigDecimal.valueOf(100).multiply(decimal).setScale(scale, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
    }

    public static BigDecimal formatPercentData(BigDecimal decimal, int scale) {
        if (decimal == null) {
            return null;
        }
        return BigDecimal.valueOf(100).multiply(decimal).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    public static BigDecimal formatPercentData(BigDecimal decimal) {
        if (decimal == null) {
            return null;
        }
        return BigDecimal.valueOf(100).multiply(decimal);
    }

    //省略0值
    public static String string2BigDecimalStringTrimZero(String str) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        return new BigDecimal(str).stripTrailingZeros().stripTrailingZeros().toPlainString();
    }

    /**
     * 费率格式化，返回给前端：
     * 返回2位或者4位小数
     * 例如：1 返回 1.00
     * 例如：1.2 返回 1.20
     * 例如：1.21 返回 1.21
     * 例如：1.212 返回 1.2120
     * 例如：1.2121 返回 1.2121
     */
    public static String showRatio(String str) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        //
        String calc = new BigDecimal(str).stripTrailingZeros().toPlainString();
        String res = StringUtils.substringAfter(calc, ".");
        if (StringUtils.isBlank(res)) {
            return calc + ".00";
        }
        if (res.length() == 1) {
            return calc + "0";
        }
        if (res.length() == 2) {
            return calc;
        }
        if (res.length() == 3) {
            return calc + "0";
        }
        if (res.length() == 4) {
            return calc;
        }
        if (res.length() > 4) {
            return StringUtils.substring(calc, 0, calc.length() - (res.length() - 4));
        }
        return calc;

    }

    /**
     * 减法： 如果两个参数都是null返回null，否则返回运算后的值
     */
    public static BigDecimal subtract(BigDecimal minuend, BigDecimal subtrahend) {
        if (minuend == null) {
            return null;
        }
        if (subtrahend == null) {
            return minuend;
        }
        return minuend.subtract(subtrahend);
    }

    /**
     * 加法： 如果两个参数都是null返回null，否则返回运算后的值
     */
    public static BigDecimal add(BigDecimal a, BigDecimal b) {
        if (a == null) {
            return b;
        }
        if (b == null) {
            return a;
        }
        return a.add(b);
    }

    /**
     * 加法： 如果两个参数都是null返回null，否则返回运算后的值
     */
    public static BigDecimal sumAdd(BigDecimal... arg) {
        BigDecimal sum = BigDecimal.ZERO;
        for (BigDecimal decimal : arg) {
            sum = add(sum, decimal);
        }
        return sum;
    }


    /**
     * 先截取两个小数，再累加
     * 加法： 如果两个参数都是null返回null，否则返回运算后的值
     */
    public static BigDecimal addSubFirst(BigDecimal a, BigDecimal b) {
        if (a == null && b == null) {
            return BigDecimal.ZERO;
        }
        if (b == null) {
            return a.setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        if (a == null) {
            return b.setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        return a.setScale(2, BigDecimal.ROUND_HALF_UP).add(b.setScale(2, BigDecimal.ROUND_HALF_UP));
    }

    /**
     * 加法： 如果两个参数都是null返回null，否则返回运算后的值
     */
    public static String addStr(String a, String b) {
        if (StringUtils.trimToNull(a) == null) {
            return StringUtils.trimToNull(b);
        }
        if (StringUtils.trimToNull(b) == null) {
            return StringUtils.trimToNull(a);
        }
        return new BigDecimal(a).add(new BigDecimal(b)).toPlainString();
    }

    public static BigDecimal string2BigDecimal(String str, int scale) {
        if (str == null || "".equals(str.trim())) {
            return null;
        }
        return new BigDecimal(str).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    public static BigDecimal string2BigDecimal(String str) {
        if (str == null || "".equals(str.trim())) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(str).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    public static BigDecimal string2PercentBigDecimal(String str, int scale) {
        if (str == null || "".equals(str.trim())) {
            return null;
        }
        return new BigDecimal(str).divide(new BigDecimal("100"), scale, BigDecimal.ROUND_HALF_UP);
    }

    public static String max(String buyLimitMin, String buyMinLimit) {
        if (StringUtils.isBlank(buyLimitMin) && StringUtils.isBlank(buyMinLimit)) {
            return BigDecimal.ZERO.toPlainString();
        }
        if (StringUtils.isBlank(buyLimitMin)) {
            return buyMinLimit;
        }
        if (StringUtils.isBlank(buyMinLimit)) {
            return buyLimitMin;
        }
        BigDecimal minLimit = new BigDecimal(buyLimitMin);
        BigDecimal limitMin = new BigDecimal(buyMinLimit);
        BigDecimal response = minLimit.compareTo(limitMin) >= 0 ? minLimit : limitMin;
        return response.toPlainString();
    }

    public static BigDecimal max(BigDecimal b1, BigDecimal b2) {
        if (b1 == null && b2 == null) {
            return BigDecimal.ZERO;
        }
        if (b1 == null) {
            return b2;
        }
        if (b2 == null) {
            return b1;
        }
        BigDecimal response = b1.compareTo(b2) >= 0 ? b1 : b2;
        return response;
    }

    public static String min(String buyLimitMin, String buyMinLimit) {
        if (StringUtils.isBlank(buyLimitMin) && StringUtils.isBlank(buyMinLimit)) {
            return BigDecimal.ZERO.toPlainString();
        }
        if (StringUtils.isBlank(buyLimitMin)) {
            return buyMinLimit;
        }
        if (StringUtils.isBlank(buyMinLimit)) {
            return buyLimitMin;
        }
        BigDecimal minLimit = new BigDecimal(buyLimitMin);
        BigDecimal limitMin = new BigDecimal(buyMinLimit);
        BigDecimal response = minLimit.compareTo(limitMin) >= 0 ? limitMin : minLimit;
        return response.toPlainString();
    }


    public static BigDecimal formatBigDecimal(BigDecimal decimal, int scale) {
        if (decimal == null) {
            return BigDecimal.ZERO;
        }
        return decimal.setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    public static String min(BigDecimal source, BigDecimal target) {
        if (source == null && target == null) {
            return null;
        }
        if (source == null) {
            return target.toPlainString();
        }
        if (target == null) {
            return source.toPlainString();
        }
        BigDecimal response = source.compareTo(target) >= 0 ? target : source;
        return response.toPlainString();
    }

    /**
     * @return a / b ,结果保留4位小数
     */
    public static BigDecimal divide(BigDecimal a, BigDecimal b) {
        if (a == null || b == null) return null;
        if (BigDecimal.ZERO.compareTo(b) == 0) return BigDecimal.ZERO;
        return a.divide(b, 4, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * @param a
     * @param b
     * @param resultScale 指定结果的小数位数，必须大于0
     * @return
     */
    public static BigDecimal divide(BigDecimal a, BigDecimal b, int resultScale) {
        if (a == null || b == null) return null;
        if (BigDecimal.ZERO.compareTo(b) == 0) return BigDecimal.ZERO;
        return a.divide(b, resultScale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * @return 除后乘以100，结果保留2位小数
     */
    public static BigDecimal divideThenMulti100(BigDecimal a, BigDecimal b) {
        if (a == null || b == null) return null;
        if (BigDecimal.ZERO.compareTo(b) == 0) return BigDecimal.ZERO;
        return a.divide(b, 6, BigDecimal.ROUND_HALF_UP).multiply(ONE_HUNDRED).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * @return 乘以100，结果保留2位小数
     */
    public static BigDecimal multi100(BigDecimal a) {
        if (Objects.isNull(a)) return null;
        return a.multiply(ONE_HUNDRED).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    public static String multi100(String a) {
        if (StrUtil.isEmpty(a)) return null;
        BigDecimal decimal = multi100(str2BigDecimal(a));
        return  bigDecimal2String(decimal, 2);
    }

    /**
     * 值为null返回数值0
     */
    public static BigDecimal null2zero(BigDecimal a) {
        if (a == null) return BigDecimal.ZERO;
        return a;
    }

    /**
     * 值为null返回数值0
     */
    public static BigDecimal null2NumberOne(BigDecimal a) {
        if (a == null) return BigDecimal.ONE;
        return a;
    }


    public static BigDecimal addTreatAsZeroIfnull(BigDecimal a, BigDecimal b) {
        if (a == null) {
            return b;
        }
        if (b == null) {
            return a;
        }
        return a.add(b);
    }

    /**
     * 参数为null 或者 小于0
     *
     * @param a
     * @return
     */
    public static boolean lessThanZeroOrIsnull(BigDecimal a) {
        if (a == null || BigDecimal.ZERO.compareTo(a) > 0) {
            return true;
        }
        return false;
    }

    public static BigDecimal str2BigDecimal(String decimal) {
        if (StringUtils.isEmpty(decimal)) {
            return null;
        }
        if (decimal.contains(",")) {
            decimal = decimal.replaceAll(",", "");
        }
        return new BigDecimal(decimal);
    }

    public static String docFormat(BigDecimal bigDecimal) {
        if (Objects.isNull(bigDecimal)) {
            return "0.00";
        }
        DecimalFormat decimal2 = new DecimalFormat("#,###,##0.00");
        if (isNotNull(bigDecimal)) {
            return decimal2.format(bigDecimal);
        }
        return "";
    }
    public static String docFormat2(BigDecimal bigDecimal) {
        if (Objects.isNull(bigDecimal)) {
            return "0.0000";
        }
        DecimalFormat decimal2 = new DecimalFormat("#,###,##0.0000");
        if (isNotNull(bigDecimal)) {
            return decimal2.format(bigDecimal);
        }
        return "";
    }

    /**
     * 返回乘以100后的值,返回小数点后两位
     * @param bigDecimal
     * @return
     */
    public static String multiply100(BigDecimal bigDecimal) {
        return bigDecimal2String(BigDecimalUtil.multiply(bigDecimal, new BigDecimal("100")), 2);
    }

    /**
     * 返回乘以1000后的值,返回小数点后两位
     * @param bigDecimal
     * @return
     */
    public static String multiply1000(BigDecimal bigDecimal) {
        return bigDecimal2String(BigDecimalUtil.multiply(bigDecimal, new BigDecimal("1000")), 2);
    }

    /**
     * 返回乘以10000后的值,返回小数点后两位
     * @param bigDecimal
     * @return
     */
    public static String multiply10000(BigDecimal bigDecimal) {
        return bigDecimal2String(BigDecimalUtil.multiply(bigDecimal, new BigDecimal("10000")), 2);
    }

    /**
     * 返回乘以10000后的值,返回小数点后两位
     * @param bigDecimal
     * @return
     */
    public static String div10000(BigDecimal bigDecimal) {
        return bigDecimal2String(BigDecimalUtil.divide(bigDecimal, new BigDecimal("10000")),0);
    }

}
